/**
 * @class Bible
 * Bible core utilities and functions.
 * @singleton
 */
var Bible = {
    /**
     * The version of the framework
     * @type String
     */
    version : '1.6',

    /**
     * logging This property controls all js logging into firebug. SET IT TO FALSE for production deployment. <br />
     * @type Boolean
     */
    logging: true,

    /**
     * @type Object
     */
    loggedUser: BibleLoggedUser,

    stateId: 'Bible',

    // global packages
    common: {},
    data: {},
    form: {},
    grid: {},
    util: {},
    plugins: {},

    // project packages
    records: {
        keywords: BibleRecordsKeywords
    },

    searchPageSize: 10,

    // default values
    defaults: {
        layout: 'box',
        references: false,
        titles: true,
        fontSize: 14
    }
};

delete BibleLoggedUser;
delete BibleRecordsKeywords;

Bible.records.books = [
    [1,  "Genesa", 50],
    [2,  "Exodul", 40],
    [3,  "Leviticul", 27],
    [4,  "Numeri", 36],
    [5,  "Deuteronomul", 34],
    [6,  "Iosua", 24],
    [7,  "Judec\u0103tori", 21],
    [8,  "Rut", 4],
    [9,  "1 Samuel", 31],
    [10, "2 Samuel", 24],
    [11, "1 \u00cemp\u0103ra\u0163i", 22],
    [12, "2 \u00cemp\u0103ra\u0163i", 25],
    [13, "1 Cronici", 29],
    [14, "2 Cronici", 36],
    [15, "Ezra", 10],
    [16, "Neemia", 13],
    [17, "Estera", 10],
    [18, "Iov", 42],
    [19, "Psalmi", 150],
    [20, "Proverbe", 31],
    [21, "Eclesiastul", 12],
    [22, "C\u00e2ntarea c\u00e2nt\u0103rilor", 8],
    [23, "Isaia", 66],
    [24, "Ieremia", 52],
    [25, "Pl\u00e2ngerile lui Ieremia", 5],
    [26, "Ezechiel", 48],
    [27, "Daniel", 12],
    [28, "Osea", 14],
    [29, "Ioel", 3],
    [30, "Amos", 9],
    [31, "Obadia", 1],
    [32, "Iona", 4],
    [33, "Mica", 7],
    [34, "Naum", 3],
    [35, "Habacuc", 3],
    [36, "\u0162efania", 3],
    [37, "Hagai", 2],
    [38, "Zaharia", 14],
    [39, "Maleahi", 4],
    [40, "Matei", 28],
    [41, "Marcu", 16],
    [42, "Luca", 24],
    [43, "Ioan", 21],
    [44, "Faptele Apostolilor", 28],
    [45, "Romani", 16],
    [46, "1 Corinteni", 16],
    [47, "2 Corinteni", 13],
    [48, "Galateni", 6],
    [49, "Efeseni", 6],
    [50, "Filipeni", 4],
    [51, "Coloseni", 4],
    [52, "1 Tesaloniceni", 5],
    [53, "2 Tesaloniceni", 3],
    [54, "1 Timotei", 6],
    [55, "2 Timotei", 4],
    [56, "Tit", 3],
    [57, "Filimon", 1],
    [58, "Evrei", 13],
    [59, "Iacov", 5],
    [60, "1 Petru", 5],
    [61, "2 Petru", 3],
    [62, "1 Ioan", 5],
    [63, "2 Ioan", 1],
    [64, "3 Ioan", 1],
    [65, "Iuda", 1],
    [66, "Apocalipsa", 22]
];


/**
 * deepCloneObject
 * Function that deep-clones a javascript object.
 *
 * @param {Object} obj javascript-object
 * @return {Object} c cloned javascript-object
 */
Bible.deepCloneObject = function(obj) {
    if (typeof obj !== 'object' || obj == null) {
        return obj;
    }

    var c = obj instanceof Array ? [] : {};

    for (var i in obj) {
        var prop = obj[i];
        if (typeof prop == 'object') {
            if (prop instanceof Array) {
                c[i] = [];
                for (var j = 0; j < prop.length; j++) {
                    if (typeof prop[j] != 'object') {
                        c[i].push(prop[j]);
                    } else {
                        c[i].push(Bible.deepCloneObject(prop[j]));
                    }
                }
            } else {
                c[i] = Bible.deepCloneObject(prop);
            }
        } else {
            c[i] = prop;
        }
    }

    return c;
};

/**
 * Method used to compare 2 objects.
 *
 * @param {Object} one the first object
 * @param {Object} two the second object
 * @param {Array} skippedProperties - optional array of properties to be skipped by this comparison
 * @return {Boolean}
 */
Bible.deepEquals = function(one, two, skippedProperties) {

    /**
     * Returns true if object one equals object two
     * @private
     * @param one
     * @param two
     */
    function objectEquals(one, two, skippedProperties) {
        var equals = true;
        if (!one || !two){
            return false;
        }

        for (var propertyName in one) {

            if (skippedProperties.indexOf(propertyName) > -1) {
                continue;
            }

            if (one[propertyName] != null && two[propertyName] == null) {
                //                console.log("false ",one,' or ', two, ' no prop ', propertyName);
                equals = false;
            }
            else if (one[propertyName] != null && two[propertyName] != null) {
                if (typeof one[propertyName] == 'object' &&  typeof two[propertyName] == 'object') {
                    equals = equals && Bible.deepEquals(one[propertyName], two[propertyName], skippedProperties);
                } else {
                    equals = equals && (one[propertyName]==two[propertyName]);
                }
            }
        }

        return equals;
    }

    var oneEqualsTwo = objectEquals(one, two, skippedProperties || []),
        twoEqualsOne = objectEquals(two, one, skippedProperties || []);

    return (oneEqualsTwo && twoEqualsOne);
};

(function(){
    var VERSE_URL = 'servlets/verse.php',
        SPACES_REG_EXP = /  /g,
        enterRegExp      = new RegExp(Ext.escapeRe('\n'), 'g'),

		BOOK_ID_KEYS = [
			'gen', 'ex', 'lev', 'num', 'deut', 'ios', 'jud', 'rut', '1sam', '2sam', '1imp', '2imp', '1cro', '2cro', 'ezra', 'neem', 'est', 'iov', 'ps', 'prov', 'ecl', 'cant', 'isa', 'ier', 'plan', 'ezec', 'dan', 'osea', 'ioel', 'amos', 'obad', 'iona', 'mica', 'naum', 'hab', 'tef', 'hag', 'zah', 'mal', 'mat', 'mar', 'luc', 'ioan', 'fap', 'rom', '1cor', '2cor', 'gal', 'efes', 'filip', 'col', '1tes', '2tes', '1tim', '2tim', 'tit', 'filim', 'evr', 'iac', '1pet', '2pet', '1ioan', '2ioan', '3ioan', 'iuda', 'apoc'
		],
		REF_FIND_REG_EXP = /(((Gen|Ex|Lev|Num|Deut|Ios|Jud|Rut|1\s?Sam|2\s?Sam|1\s?Împ|1\s?Imp|2\s?Împ|2\s?Imp|1\s?Cro|2\s?Cro|Ezra|Neem|Est|Iov|Ps|Prov|Ecl|Cânt|Cant|Isa|Plân|Ier|Ezec|Dan|Osea|Ioel|Amos|Obad|Iona|Mica|Naum|Hab|Ţef|Tef|Hag|Zah|Mal|Mat|Mar|Luc|Ioan|Fap|Rom|1\s?Cor|2\s?Cor|Gal|Efes|Filip|Col|1\s?Tes|2\s?Tes|1\s?Tim|2\s?Tim|Tit|Filim|Evr|Iac|1\s?Pet|2\s?Pet|1\s?Ioan|2\s?Ioan|3\s?Ioan|Iuda|Apoc)\w*\s?\w*\s?\w*)\s(\d+)\.(\d+)(-\d+)?)/gi,
		
        // diacritics RegExp
        CHAR_ESCAPE_A_REG_EXP = /([aâă])/gi,
        CHAR_ESCAPE_I_REG_EXP = /([iî])/gi,
        CHAR_ESCAPE_S_REG_EXP = /([sş])/gi,
        CHAR_ESCAPE_T_REG_EXP = /([tţ])/gi;
		
	function removeDiacritics(text) {
		return text.replace(CHAR_ESCAPE_A_REG_EXP, "a").
					replace(CHAR_ESCAPE_I_REG_EXP, "i").
					replace(CHAR_ESCAPE_S_REG_EXP, "s").
					replace(CHAR_ESCAPE_T_REG_EXP, "t");
	}
			
	function findRefInsideText(fullMatch, total, bookLong, book, chapter, verse) {
		book = removeDiacritics(book.replace(' ', '').toLowerCase());
		
		var idx = BOOK_ID_KEYS.indexOf(book);
		if(idx > -1){
			var r = removeDiacritics(Bible.records.books[idx][1].replace(' ', '').toLowerCase());
			bookLong = removeDiacritics(bookLong.replace(' ', '').toLowerCase());
			//console.debug(r, bookLong);
			// if record text did not match
			if(r.indexOf(bookLong) != 0){
				idx = -1;
			}
		}
		book = idx + 1;
		if(book > 0){
			return ['<span class="ref" ext:qwidth="200" ext:qtip=" " ext:qurl="',
				VERSE_URL,
				'?b=', book,
				'&c=', chapter,
				'&v=', verse,
				'">', fullMatch, '</span>'
			].join('');
		} else {
			return fullMatch;
		}
	}

    Ext.apply(Bible, {
        /**
         * renderer Terms Highlight
         * @param {Object} val
         * @param {Object} metaData
         * @param {Ext.data.Record} record
         * @param {Number} rowIndex
         * @param {Number} colIndex
         * @param {Ext.data.Store} store
         */
        rendererHighlight : function(val, metaData, record, rowIndex, colIndex, store) {
            var searchField = store.searchField,
                showKeywords = store.showKeywords;
            //console.debug('rendererHighlight showKeywords', showKeywords);
            if((!searchField || !searchField.hasSearch) && !showKeywords){
                return val;
            }
            val = Bible.highlightTerms(val, store).text;
            return val;
        },

        /**
         * @param {String} v
         * @return {String} v
         */
        rendererComments : function(v){
            v = Ext.util.Format.htmlEncode(v);
			v = v.replace(REF_FIND_REG_EXP, findRefInsideText);
            v = v.replace(enterRegExp, '<br/>');
            v = v.replace(SPACES_REG_EXP, ' &nbsp;');
            return v;
        },

        /**
         * Escapes diacritics in the passed string for use in a regular expression
         * @param {String} s
         * @return {String}
         */
        escapeDiacriticsRe : function(s){
            return s.replace(CHAR_ESCAPE_A_REG_EXP, "[aâă]").
                replace(CHAR_ESCAPE_I_REG_EXP, "[iî]").
                replace(CHAR_ESCAPE_S_REG_EXP, "[sş]").
                replace(CHAR_ESCAPE_T_REG_EXP, "[tţ]");
        },

		highlightTerms : function(val, store) {
            var searchField = store.searchField,
                showKeywords = true,
                //showKeywords = store.showKeywords,
                highlightsTerms = searchField ? searchField.highlightsTerms : [];
            return Bible.highlightText(val, highlightsTerms, showKeywords);
        },
		
        /**
         * @param {String} val
         * @param {String/Array} defaultTerms a Term or Array of Terms
         * @return {String} val highlighted value
         */
        highlightText : function(val, defaultTerms, showKeywords) {
            var KeywordsStore = Bible.data.KeywordsStore,
                terms = [];
            if(showKeywords){
                terms = [].concat(KeywordsStore.keywordsReplace);
            }
			if(defaultTerms){
				//console.debug('defaultTerms', defaultTerms);
				terms = terms.concat(defaultTerms);
			}
            return Ext.util.Terminology.highlight(val, terms);
        },

        /**
         * @return {Object/JSON}
         */
        getActions : function(){
            var actions = window.location.hash.split('#')[1],
                stateProvider = Ext.state.Manager.getProvider();
            return Ext.urlDecode(actions ? actions : stateProvider.get(this.stateId));
        },

        /**
         *
         * @param {String} properties
         */
        getAction : function(properties){
          var ps = Bible.getActions();
          return ps[properties];
        },

        /**
         *
         * @param {String} properties
         * @param {Object} value
         */
        setActions : function(properties, value){
            var ps = Bible.getActions(),
                stateProvider = Ext.state.Manager.getProvider(),
                encoded;
            ps[properties] = value;
            encoded = Ext.urlEncode(ps);
            stateProvider.set(this.stateId, encoded);
            window.location.hash = encoded;
        },

        /**
         *
         * @param {String} properties
         */
        removeAction : function(properties){
            var ps = Bible.getActions(),
                stateProvider = Ext.state.Manager.getProvider(),
                encoded;
            delete ps[properties];
            encoded = Ext.urlEncode(ps);
            stateProvider.set(this.stateId, encoded);
            window.location.hash = encoded;
        },

        /**
         *
         */
        isLogged : function(){
            return !!Bible.loggedUser;
        },

        /**
         *
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        info: function(message, title, fn){
            this.showMsg('INFO', message, title, fn);
        },

        /**
         *
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        error: function(message, title, fn){
            this.showMsg('ERROR', message, title, fn);
        },

        /**
         *
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        warning: function(message, title, fn){
            this.showMsg('WARNING', message, title, fn);
        },

        /**
         *
         * @param {String} level
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        showMsg: function(level, message, title, fn){
            console.info('showMsg: ', level, message, title);
            var d = Ext.Msg.getDialog("&#160;");
            if(d && d.proxy){
                delete d.animateTarget;
                d.proxy.stopFx();
            }
            Ext.Msg.show({
                title: title || i18n[level.toLowerCase()],
                msg: message,
                buttons: Ext.Msg.OK,
                minWidth: 300,
                animEl: 'app-name-version',
                icon: Ext.MessageBox[level],
                fn: fn || function(){}
            });
        },

        notifyNotLogged: function(){
            Bible.Notification.msg(i18n.login, i18n.saveNotLoggedMsg);
        },

        /**
         *
         */
        doLogout : function() {
            Ext.Ajax.request({
                url: 'auth.php?action=logout',
                success: function(){
                    console.debug('doLogout success');
                    Bible.EventManager.fireEvent('logout');
                    // TODO fix IE Bug that is not showing the last action
//                    window.location = '/'+window.location.hash;
                    window.location = '/';
                }
            });
            //TODO local hide buttons
            //window.location.reload();
//            window.location.href = 'auth.php?action=logout#' + window.location.hash;
        }
    });


    /**
     * @private
     * @param {JSON} response
     */
    function showMessage(response){
        // TODO remove all : TODO automaticaly message
        var message = response.message;
        if(message){
            Bible.showMsg(response.level, message, response.title);
        }
        // Bible.Notification.msg();
    }

    function getJsonResponse(response, options){
        // TODO try to not decode ajax request if ajax request does not need to have json response
        var jsonResponse;
        try {
            jsonResponse = Ext.decode(response.responseText, /* safe */ true);
            response.responseJson = jsonResponse;
            response.responseSuccess = jsonResponse.success;
            return jsonResponse;
        } catch (err){
//            console.warn('requestexception can not decode', response);
        }
        return false;
    }

    function onRequestComplete(connection, response, options) {
        var jsonResponse = getJsonResponse(response, options);
        if (jsonResponse) {
            showMessage(jsonResponse);
        }
    }

    function onRequestException(connection, response, options, e) {
        console.warn('requestexception', response, connection);
        if (response.isTimeout){
            console.warn("Timeout: ", options);
            Bible.Notification.msg(i18n.error, i18n.requestTimeout);
        } else {
            var jsonResponse = getJsonResponse(response, options);
            if (jsonResponse) {
                if (jsonResponse.unauthorized === true) {
                    Bible.warning(i18n.authenticationRequired, i18n.warning, function(){
                        window.location = '/';
                    });
                } else {
                    showMessage(jsonResponse);
                }
            } else {
                Bible.Notification.msg(i18n.error, i18n.unknownError);
            }
        }
    }

    /**
     * @override Ext.data.Connection
     * to handle all connection exceptions and messages that server returned.
     */
    Ext.override(Ext.data.Connection, {
        handleResponse: Ext.data.Connection.prototype.handleResponse.createInterceptor(function(response) {
            var options = response.argument.options;
            onRequestComplete(this, response, options);
        }),
        handleFailure: Ext.data.Connection.prototype.handleFailure.createInterceptor(function(response, e) {
            var options = response.argument.options;
            onRequestException(this, response, options, e);
        })
    });

})();

/**
 * @param {String} action
 * @param {Object} e
 * @param {String} servletUrl
 */
Bible.updateDBObj = function(action, e, servletUrl, success, scope) {
    var record = e.record;
    if(Bible.isLogged()){
        Ext.Ajax.request({
            url: servletUrl,
            success:function(response) {
                if(response.responseSuccess) {
                    record.commit();
                    if(success){
                        success.call(scope || window);
                    }
                } else {
                    record.reject();
                }
            },
            params: {
                action: action,
                field: e.field,
                value: e.value,
                id: record.id
            }
        });
    } else {
        //TODO save in cache
        console.warn('TODO save in cache');
//        record.commit();
        if(success){
            success.call(scope || window);
        }
        Bible.notifyNotLogged();
    }
};

Bible.copyToClipboard = function (s) {
    // ie
    if (window.clipboardData && clipboardData.setData) {
        clipboardData.setData('text', s);
    } else { // others
        // TODO
//        var flashCopier = 'flashcopier';
//        if(!document.getElementById(flashcopier)) {
//            var divHolder = document.createElement('div');
//            divHolder.id = flashCopier;
//            document.body.appendChild(divHolder);
//        }
//        document.getElementById(flashCopier).innerHTML = '';
//        var divInfo = '<embed src="_clipboard.swf" FlashVars="clipboard='+encodeURIComponent(s)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
//        document.getElementById(flashCopier).innerHTML = divInfo;
    }
};

/**
 *
 */
Bible.doLogin = function() {
    var username = 'email',
        password = 'password',
        waitMsg = i18n.connecting;
    if(!this.loginWin){
        function showNormalLogin(show){
            console.debug('showNormalLogin', show);
            waitMsg = show ? i18n.connecting : i18n.resetPassword;
            var form = formPanel.getForm();
            form.findField('action').setValue(show ? 'login' : 'resetpasswd');
            form.findField(password).setDisabled(!show);
            if(!show){
                form.findField(password).reset();
            }

            formPanel.resetPassword.setVisible(!show);
            formPanel.login.setVisible(show);

            form.findField('forgotPassword').setVisible(show);
            form.findField('normalLogin').setVisible(!show);
        }
        function doLoginHandler(){
            if(formPanel.getForm().isValid()){
                formPanel.getForm().submit({
                    method:'POST',
                    waitTitle: i18n.login,
                    waitMsg: waitMsg,
                    scope: this,
                    success: function(form, action) {
                        console.debug('success', form, action);
                        if(form.findField('action').getValue() == 'login'){
                            // simulate refresh
                            formPanel.remove(form.findField('action'));
                            form.url = window.location.href;
                            form.standardSubmit = true;
                            form.submit();
                        }
                    }
                });
            } else {
                console.warn('form is not valid');
            }
        }

        var formPanel = new Ext.form.FormPanel({
            labelWidth: 100,
            labelAlign: 'right',
            url:'auth.php',
            cls: 'x-panel-mc', // for background color (like frame)
            defaultType: 'textfield',
            monitorValid:true,
            bodyStyle: 'padding-top: 8px',
            defaults: {
                anchor: '-8'
            },
            keys: [
                {
                    key: Ext.EventObject.ENTER,
                    scope: this,
                    fn: doLoginHandler
                }
            ],
            items:[
                {
                    xtype: 'hidden',
                    name: 'action',
                    value: 'login'
                },
                {
                    fieldLabel: i18n.email,
                    name: username,
                    el: 'input_username',
                    vtype: 'email',
                    allowBlank:false
                },
                {
                    fieldLabel: i18n.password,
                    name: password,
                    el: 'input_password',
                    inputType:'password',
                    minLength: 6,
                    allowBlank: false
                },
                {
                    xtype: 'displayfield',
                    name: 'forgotPassword',
                    value: '<a href="#" >'+i18n.forgotPassword+'</a>',
                    listeners: {
                        afterrender: function(){
                            this.el.select('a').on('click',function(){
                                showNormalLogin(false);
                            }, this);
                        }
                    }
                },
                {
                    xtype: 'displayfield',
                    name: 'normalLogin',
                    hidden: true,
                    value: '<a href="#" >'+i18n.normalLogin+'</a>',
                    listeners: {
                        afterrender: function(){
                            this.el.select('a').on('click',function(){
                                showNormalLogin(true);
                            }, this);
                        }
                    }
                }
            ],
            buttons:[
                {
                    text: i18n.login,
                    ref: '/login',
                    type: 'submit',
					iconCls: 'login-action',
                    formBind: true,
                    disabled: true,
                    scope: this,
                    handler: doLoginHandler
                },
                {
                    text: i18n.resetPassword,
                    ref: '/resetPassword',
                    formBind: true,
                    scope: this,
                    hidden: true,
                    handler: doLoginHandler
                },
                {
                    text: i18n.cancel,
                    scope: this,
                    handler: function(){
                        this.loginWin.hide();
                    }
                }
            ]
        });
        this.loginWin = new Ext.Window({
            title: i18n.login,
            closeAction: 'hide',
			iconCls: 'login',
            width: 350,
            autoHeight: true,
            modal: true,
            resizable: false,
            listeners: {
                show: function(){
                    showNormalLogin(true);
                    (function(){
                        formPanel.getForm().findField(username).focus();
                    }).defer(300);
                }
            },
            items: [formPanel]
        });
    }
    this.loginWin.show();
};

/**
 *
 */
Bible.showRegisterForm = function() {
    //var captchaURL = "include/captcha/CaptchaSecurityImages.php?width=100&height=40&characters=4&t=";
    if(!this.registerWin){
        function doRegisterHandler(){
            if(formPanel.getForm().isValid()){
                formPanel.getForm().submit({
                    method:'POST',
                    waitTitle: i18n.register,
                    waitMsg: i18n.connecting,
                    scope: this,
                    success:function(form, action) {
                        this.registerWin.hide();
                    }
                });
            } else {
                console.warn('form is not valid');
            }
        }

//        var boxCaptcha = new Ext.BoxComponent({
//            width: 150,
//            height: 40,
//            autoEl: {
//                tag:'img',
//                id: 'activateCodeImg',
//                title : 'Click pentru alt code',
//                src: captchaURL + new Date().getTime()
//            }
//        });
//        boxCaptcha.on('render',function (){
//            var curr = Ext.get('activateCodeImg');
//            //curr.on('click', this.onCapthaChange,this);
//        },this);

        var formPanel = new Ext.form.FormPanel({
            labelWidth: 100,
            labelAlign: 'right',
            url:'register.php',
            timeout: 90, // 1 min 30 sec
            method : 'POST',
            cls: 'x-panel-mc', // for background color (like frame)
            defaultType: 'textfield',
            monitorValid:true,
            bodyStyle: 'padding-top: 8px',
            defaults: {
                anchor: '-8'
            },
            keys: [
                {
                    key: Ext.EventObject.ENTER,
                    scope: this,
                    fn: doRegisterHandler
                }
            ],
            items:[
                {
                    fieldLabel: i18n.email,
                    name:'username',
                    vtype: 'email',
                    allowBlank:false
                },
                {
                    fieldLabel: i18n.password,
                    name:'password',
                    id: 'registerPassword',
                    inputType:'password',
                    allowBlank:false,
                    minLength: 6
                },
                {
                    fieldLabel: i18n.confirmPassword,
                    inputType:'password',
                    vtype: 'password',
                    initialPassField: 'registerPassword',
                    allowBlank:false
                }
//                {
//                    fieldLabel: 'Confirmare',
//                    xtype: 'compositefield',
//                    items: [{
//                        xtype: 'textfield',
//                        width: 60,
//                        name: 'confirm'
//                    },
//                    boxCaptcha
//                    ]
//                }
            ],
            buttons:[
                {
                    text: i18n.register,
                    iconCls: 'save',
                    formBind: true,
                    disabled: true,
                    scope: this,
                    handler: doRegisterHandler
                },
                {
                    text: i18n.cancel,
                    scope: this,
                    handler: function(){
                        this.registerWin.hide();
                    }
                }
            ]
        });
        this.registerWin = new Ext.Window({
            title: i18n.register,
            iconCls: 'user_add',
            closeAction: 'hide',
            width: 350,
            autoHeight: true,
            modal: true,
            resizable: false,
            items: [formPanel]
        });
    }
    this.registerWin.show();
};


(function(){
    // private
    function doSubmitHandler(formPanel, win, scope){
        if(formPanel.getForm().isValid()){
            formPanel.getForm().submit({
                method:'POST',
                waitTitle: i18n.changePassword,
                waitMsg: i18n.saving + '...',
                scope: scope,
                success:function() {
                    win.hide();
                }
            });
        } else {
            console.warn('form is not valid');
        }
    }

    /**
     *
     */
    Bible.showResetPassWin = function() {
        if(!this.resetPassWin){
            var formPanel = new Ext.form.FormPanel({
                labelWidth: 100,
                labelAlign: 'right',
                url:'auth.php',
                timeout: 90, // 1 min 30 sec
                method : 'POST',
                cls: 'x-panel-mc', // for background color (like frame)
                defaultType: 'textfield',
                monitorValid:true,
                bodyStyle: 'padding-top: 8px',
                defaults: {
                    anchor: '-8'
                },
                keys: [
                    {
                        key: Ext.EventObject.ENTER,
                        scope: this,
                        fn: function(){
                            doSubmitHandler(formPanel, this.resetPassWin, this);
                        }
                    }
                ],
                items:[
                    {
                        xtype: 'hidden',
                        name: 'action',
                        value: 'changePassword'
                    },
                    {
                        fieldLabel: i18n.password,
                        name:'password',
                        id: 'resetPassword',
                        inputType:'password',
                        allowBlank:false,
                        minLength: 6
                    },
                    {
                        fieldLabel: i18n.confirmPassword,
                        inputType:'password',
                        vtype: 'password',
                        initialPassField: 'resetPassword',
                        allowBlank:false
                    }
                ],
                buttons:[
                    {
                        text: i18n.save,
                        iconCls: 'save',
                        formBind: true,
                        disabled: true,
                        scope: this,
                        handler: function(){
                            doSubmitHandler(formPanel, this.resetPassWin, this);
                        }
                    }
                ]
            });

            /**
             * @property resetPassWin
             * @type Ext.Window
             */
            this.resetPassWin = new Ext.Window({
                title: i18n.changePassword,
                iconCls: 'key',
                closeAction: 'hide',
                width: 350,
                autoHeight: true,
                modal: true,
                closable: false,
                resizable: false,
                items: [formPanel]
            });
        }
        this.resetPassWin.show();
    };

    /**
     *
     */
    Bible.showChangePassWin = function() {
        if(!this.changePassWin){
            var formPanel = new Ext.form.FormPanel({
                labelWidth: 100,
                labelAlign: 'right',
                url:'auth.php',
                timeout: 90, // 1 min 30 sec
                method : 'POST',
                cls: 'x-panel-mc', // for background color (like frame)
                defaultType: 'textfield',
                monitorValid:true,
                bodyStyle: 'padding-top: 8px',
                defaults: {
                    anchor: '-8'
                },
                keys: [
                    {
                        key: Ext.EventObject.ENTER,
                        scope: this,
                        fn: function(){
                            doSubmitHandler(formPanel, this.changePassWin, this);
                        }
                    }
                ],
                items:[
                    {
                        xtype: 'hidden',
                        name: 'action',
                        value: 'changePassword'
                    },
                    {
                        fieldLabel: i18n.oldPassword,
                        name:'oldPassword',
                        inputType:'password',
                        allowBlank:false,
                        minLength: 6
                    },
                    {
                        fieldLabel: i18n.password,
                        name:'password',
                        id: 'changePassword',
                        inputType:'password',
                        allowBlank:false,
                        minLength: 6
                    },
                    {
                        fieldLabel: i18n.confirmPassword,
                        inputType:'password',
                        vtype: 'password',
                        initialPassField: 'changePassword',
                        allowBlank:false
                    }
                ],
                buttons:[
                    {
                        text: i18n.save,
                        iconCls: 'save',
                        formBind: true,
                        disabled: true,
                        scope: this,
                        handler: function(){
                            doSubmitHandler(formPanel, this.changePassWin, this);
                        }
                    },
                    {
                        text: i18n.cancel,
                        scope: this,
                        handler: function(){
                            this.changePassWin.hide();
                        }
                    }
                ]
            });

            /**
             * @property changePassWin
             * @type Ext.Window
             */
            this.changePassWin = new Ext.Window({
                title: i18n.changePassword,
                iconCls: 'key',
                closeAction: 'hide',
                width: 350,
                autoHeight: true,
                modal: true,
                resizable: false,
                items: [formPanel]
            });
        }
        this.changePassWin.show();
    };


    /**
     *
     */
    Bible.showPreferencesWin = function() {
        if(!this.preferencesWin){
            // TODO not done change email yet
//
//            var formPanel = new Ext.form.FormPanel({
//                title: i18n.general,
//                labelWidth: 100,
//                labelAlign: 'right',
//                url:'preferences.php', // TODO
//                timeout: 90, // 1 min 30 sec
//                method : 'POST',
//                cls: 'x-panel-mc', // for background color (like frame)
//                defaultType: 'textfield',
//                monitorValid:true,
//                bodyStyle: 'padding-top: 8px',
//                defaults: {
//                    anchor: '-8'
//                },
//                keys: [
//                    {
//                        key: Ext.EventObject.ENTER,
//                        scope: this,
//                        fn: function(){
//                            //doSubmitHandler(formPanel, this.changePassWin, this);
//                        }
//                    }
//                ],
//                items:[
//                    {
//                        fieldLabel: i18n.email,
//                        name:'username',
//                        vtype: 'email',
//                        value: (Bible.loggedUser) ? Bible.loggedUser.email : 'demo@bibliaonline.ro',
//                        //disabled: true,
//						readOnly: true,
//                        allowBlank:false
//                    }
//                ],
//                buttons:[
//                    {
//                        text: i18n.save,
//                        iconCls: 'save',
//                        disabled: true
//                    },
//                    {
//                        text: i18n.cancel,
//                        disabled: true
//                    }
//                ]
//            });


            /**
             * @property preferencesWin
             * @type Ext.Window
             */
            this.preferencesWin = new Ext.Window({
                title: i18n.preferences,
                iconCls: 'preferences',
                closeAction: 'hide',
                width: 800,
                minWidth: 700,
                height: 470,
                minHeight: 300,
                maximizable: true,
                collapsible: true,
                tbar: {
                    hidden: !Bible.loggedUser,
                    items:[
                        {
                            text: i18n.changePassword,
                            iconCls: 'key',
                            scope: this,
                            handler: function(){
                                Bible.showChangePassWin();
                            }
                        },
                        '-'
                    ]
                },
                layout: 'fit',
                items: [
                    new Ext.TabPanel({
                        activeTab: 0,
                        border: false,
                        bodyBorder: false,
                        items: [
//                            formPanel,
                            new Bible.KeywordsPanel({
								ref: '/keywordsPanel',
                                border: false,
                                title: i18n.keywords
                            })
                        ]
                    })
                ]
            });
//			this.preferencesWin.keywordsPanel.saveAndCloseButton.on({
//				scope: this.preferencesWin,
//				click: function(){
//                    (function(){
//                        this.hide(); // TODO fix: add and hit saveAndClose -> when open second time grid is disabled
//                    }).defer(1000, this);
//				}
//			});
        }
        this.preferencesWin.show();
    };
})();

/**
 *
 */
Bible.showDocs = function() {
    if(!this.docWin){
        this.docWin = new Ext.Window({
            title: i18n.info,
            autoLoad: 'docs/' + i18n.langCode + '/docs.html?' + Bible.version,
            iconCls: 'icon-docs',
            bodyStyle: 'padding: 10px',
            cls: 'docs-window',
            autoScroll: true,
            closeAction: 'hide',
            width: 750,
            height: 450,
            maximizable: true,
            buttons: [
                {
                    text: i18n.close,
                    scope: this,
                    handler: function(){
                        this.docWin.hide();
                    }
                }
            ]
        });
    }
    this.docWin.show();
};

//_logger_block_start - don't remove this line (used in build.xml)
(function(){
    function setConsoleFunction(fn, force){
        if(!window.console || !Bible.logging) {
            window.console = {};
        }

        var copyFn = force ? Ext.apply : Ext.applyIf;
        copyFn(window.console, {
            info: fn,
            log: fn,
            dir: fn,
            warn: fn,
            debug: fn,
            time: fn,
            timeEnd: fn,
            profile: fn,
            profileEnd: fn
        });
    }

    if(Bible.logging){
//        if(Ext.isIE && window.console && window.console.log){
//            setConsoleFunction(console.log, false);
//        }
        setConsoleFunction(Ext.emptyFn, false);
    } else {
        setConsoleFunction(Ext.emptyFn, true);
    }
})();
//_logger_block_end



/**
 * @class Bible.Notification
 * @extends Object
 * @singleton
 */
Bible.Notification = (function(){
    var msgCt,
        firstTime = true;
    function createBox(t, s){
        return [
            '<div class="msg">',
                '<h3>',
                    '<div class="x-tool x-tool-close"></div>',
                    t,
                '</h3>', s,
            '</div>'
        ].join('');
    }

    return {
        /**
         * @cfg {String} id
         */
        id: 'notification-msg-div',

        /**
         * @cfg {String/Object} containerEl
         */
        /**
         * @cfg {Number} hideInterval
         */
        hideInterval: 10,

        /**
         * @cfg {String} showAnchor
         */
        showAnchor: 't',

        /**
         * @cfg {String} hideAnchor
         */
        hideAnchor: 'r',

        init: function(config){
            Ext.apply(this, config);
        },

        /**
         *
         * @param {String} title
         * @param {String/Array} format
         * @param {String} icon TODO
         */
        msg : function(title, format, icon){
            // TODO nmatei - test in chrome (first time appears in top-middle not in top-right
            var me = this,
                containerEl = me.containerEl = me.containerEl || document.body;
            if(!msgCt){
                msgCt = Ext.DomHelper.insertFirst(containerEl, {id: me.id}, true);
            }
            msgCt.alignTo(containerEl, 't-t');
            if(firstTime){
                msgCt.alignTo(containerEl, 't-t');
                firstTime = false;
            }
//            msgCt.alignTo(me.containerEl, 'tr-tr');
            var s = String.format.apply(String, Array.prototype.slice.call(arguments, 1)),
                m = Ext.DomHelper.append(msgCt, {
                    html : createBox(title, s)
                }, true);
            console.info('msg: ', title, s);
            m.slideIn(me.showAnchor).pause(me.hideInterval).fadeOut({remove:true});
//            m.select('span.close').on('click', function(){
            m.select('div.x-tool-close').on('click', function(){
                m.stopFx().fadeOut({remove:true});
            });
        }
    };
})();
